<template>
  <n-card :border="false">
    <n-alert type="warning" class="alert_small m-b-10">
      温馨提示：管理课程资料、包括上传、删除、停用等。
    </n-alert>
    <n-alert :show-icon="false" class="m-b-10">
      <n-form :model="search_param" class="search-forms"
              inline
              :show-feedback="false"
              label-placement="left"
              @keydown.enter.prevent="handleSubmitSearch">
        <n-form-item label="资料名称">
          <n-input v-model:value="search_param.title" placeholder="输入资料名称查询" clearable/>
        </n-form-item>
        <n-form-item label="课程">
          <n-select v-model:value="search_param.sid" :options="courseOptions"
                    label-field="name"
                    value-field="id"
                    placeholder="请选择课程"
                    :render-label="renderLabelSuffix"
                    style="width: 320px" clearable/>
        </n-form-item>
        <n-form-item label="状态">
          <n-select v-model:value="search_param.status" :options="statusOption" style="width: 130px;" clearable/>
        </n-form-item>
        <n-form-item label="是否精选">
          <n-select v-model:value="search_param.selected" :options="selectedOption" style="width: 100px;" clearable/>
        </n-form-item>
        <n-form-item>
          <search-button-group @submit="handleSubmitSearch"
                               @reset="()=>(search_param.sid=null,search_param.status=null,search_param.selected=null,search_param.title=null)"/>
        </n-form-item>
      </n-form>
    </n-alert>
    <data-table ref="data_list"
                :columns="columns"
                :action-column="actionColumn"
                :row-key="(row:Recordable) => row.id"
                :params="search_param"
                list-url="course_m/list"
                default-serial-number
                serial-number-title="序号">
      <template #toolbarLeft>
        <n-button type="success" v-permission="['materials:add']" @click="()=>(addEditModel=true)">
          <n-icon :size="18">
            <AddSharp/>
          </n-icon>
          新增
        </n-button>
      </template>
    </data-table>
    <!--新增、修改课程资料-->
    <n-modal v-model:show="addEditModel"
             :title="addEditForm.id?'修改课程资料':'新增课程资料'" :mask-closable="false"
             :show-icon="false" preset="dialog" style="width: 560px;" @after-leave="closeAddEditModel">
      <n-form ref="addEditFormRef" :model="addEditForm" :rules="addEditFormRules" require-mark-placement="left"
              label-width="auto" label-placement="left">
        <n-grid :cols="22" :x-gap="24">
          <n-form-item-gi :span="22" label="所属课程" path="sId">
            <n-select v-model:value="addEditForm.sId" :options="courseOptions"
                      label-field="name"
                      value-field="id"
                      placeholder="请选择课程"
                      :render-label="renderLabelSuffix"
                      clearable/>
          </n-form-item-gi>
        </n-grid>
        <n-grid :cols="22" :x-gap="24">
          <n-form-item-gi :span="22" label="资料标题" path="title">
            <n-input v-model:value="addEditForm.title" placeholder="请填写资料标题" clearable/>
          </n-form-item-gi>
        </n-grid>
        <n-grid :cols="22" :x-gap="24">
          <n-form-item-gi :span="11" label="图片" path="img">
              <image-selection v-model:value="addEditForm.img"/>
          </n-form-item-gi>
          <n-form-item-gi :span="11" label="课程资料" path="src">
              <custom-upload v-model:value="addEditForm.src" type="box"/>
          </n-form-item-gi>
        </n-grid>
<!--        <n-grid :cols="22" :x-gap="24">-->
<!--          <n-form-item-gi :span="22" label="本地资料" path="isLocal">-->
<!--            <n-radio-group v-model:value="addEditForm.isLocal" name="isLocal">-->
<!--              <n-radio :value="1" label="是"/>-->
<!--              <n-radio :value="0" label="否"/>-->
<!--            </n-radio-group>-->
<!--          </n-form-item-gi>-->
<!--        </n-grid>-->
<!--        <n-grid :cols="22" :x-gap="24" v-if="addEditForm.isLocal==0">-->
<!--          <n-form-item-gi :span="22" label="远程地址" path="src">-->
<!--            <n-input v-model:value="addEditForm.src" placeholder="请填写资料远程地址" clearable/>-->
<!--          </n-form-item-gi>-->
<!--        </n-grid>-->
        <n-grid :cols="22" :x-gap="24">
          <n-form-item-gi :span="22" label="是否精选" path="selected">
            <n-switch :round="false" v-model:value="addEditForm.selected" :checked-value="1" :unchecked-value="0">
              <template #checked>
                是
              </template>
              <template #unchecked>
                否
              </template>
            </n-switch>
          </n-form-item-gi>
        </n-grid>
        <n-grid :cols="22" :x-gap="24">
          <n-form-item-gi :span="22" label="可否下载" path="isDownload">
            <n-radio-group v-model:value="addEditForm.isDownload" name="isDownload">
              <n-radio :value="1" label="可下载"/>
              <n-radio :value="0" label="不可下载"/>
            </n-radio-group>
          </n-form-item-gi>
        </n-grid>
        <n-grid :cols="22" :x-gap="24">
          <n-form-item-gi :span="11" label="预览量" path="preview">
            <n-input-number v-model:value="addEditForm.preview" :show-button="false" clearable/>
          </n-form-item-gi>
          <n-form-item-gi :span="11" label="下载量" path="download">
            <n-input-number v-model:value="addEditForm.download" :show-button="false" clearable/>
          </n-form-item-gi>
        </n-grid>
        <n-grid :cols="22" :x-gap="24">
          <n-form-item-gi :span="11" label="排序" path="sort">
            <n-input-number v-model:value="addEditForm.sort" :show-button="false" clearable/>
          </n-form-item-gi>
          <n-form-item-gi :span="11" label="点赞量" path="likes">
            <n-input-number v-model:value="addEditForm.likes" :show-button="false" clearable/>
          </n-form-item-gi>
        </n-grid>
        <n-grid :cols="22" :x-gap="24">
          <n-form-item-gi :span="11" label="状态" path="status">
            <n-switch :round="false" v-model:value="addEditForm.status" :checked-value="1" :unchecked-value="0">
              <template #checked>
                正常
              </template>
              <template #unchecked>
                停用
              </template>
            </n-switch>
          </n-form-item-gi>
        </n-grid>
      </n-form>
      <template #action>
        <n-space>
          <n-button @click="()=>(addEditModel=false)">取消</n-button>
          <n-button type="primary" :loading="handelSubmitLoading" @click="handelSubmitData">确定</n-button>
        </n-space>
      </template>
    </n-modal>
  </n-card>
</template>
<script setup lang="ts">
import {ref, reactive, h, onBeforeMount, computed} from 'vue';
import SearchButtonGroup from '@components/SearchButtonGroup';
import {
  SelectOption,
  FormInst,
  NTag,
  NPopconfirm,
  useMessage,
  UploadCustomRequestOptions,
  NImage,
  NSwitch
} from 'naive-ui';
import {delRequest, postPutRequest, getRequest} from '@/api/data.ts';
import DataTable from '@components/DataTable';
import DataTableAction from '@components/DataTable/src/components/DataTableAction';
import {AddSharp} from '@vicons/material';
import {getFileMd5, getExtension, permsJudg} from '@/util'


import {imagePreview} from '@/util';
import ImageSelection from "@components/ImageSelection";
import CustomUpload from "@components/CustomUpload"

const message = useMessage()


const courseOptions = ref<any[]>([]);
const statusOption = ref<SelectOption[]>([
  {
    label: '启用',
    value: 1,
  }, {
    label: '停用',
    value: 0,
  }
])
const selectedOption = ref<SelectOption[]>([
  {
    label: '是',
    value: 1,
  }, {
    label: '否',
    value: 0,
  }
])
const search_param = ref({
  title:<any> null,
  sid:<any> null,
  status:<any> null,
  selected:<any> null,
})
//数据表
const data_list = ref<any>();
const columns = ref([
  {
    title: '所属课程',
    key: 'courseName',
    render(row: { courseName: string, classifyName: string, gradeName: string }) {
      const name = row.courseName + '(' + row.classifyName + '/' + row.gradeName + ')';
      return h('span', null, {default: () => (name)})
    }
  }, {
    title: '资料标题',
    key: 'title',
  }, {
    title: '封面',
    key: 'img',
    width: 100,
    align: 'center',
    render(row: { img: string }) {
      if (row.img) {
        return h(NImage, {
          width: 20,
          height: 20,
          src: imagePreview(row.img)
        })
      }
    }
  }, {
    title: '精选',
    key: 'selected',
    width: 80,
    align: 'center',
    render(row: { id: number, selected: number }) {
      return h(NSwitch, {
        round: false,
        checkedValue: 1,
        uncheckedValue: 0,
        value: row.selected,
        onUpdateValue: function (value) {
          if (permsJudg('materials:selected')) { //权限 有权限进行一下操作
            row.selected = value;
            postPutRequest('course_m/up_selected', {
              id: row.id,
              selected: value
            }, 'PUT').then((result: ResponseResult) => {
              message.create(result.message, {
                type: result.code === 200 ? 'success' : 'error',
                duration: 1500,
              });
              row.selected = result.code === 200 ? value : value ? 0 : 1;
            })
          }
        }
      })
    }
  }, {
    title: '本地资料',
    key: 'isLocal',
    width: 100,
    align: 'center',
    render(row: { isLocal: number }) {
      const local = row.isLocal ? '是' : '否';
      return h('span', null, {default: () => (local)})
    }
  }, {
    title: '是否可下载',
    key: 'isDownload',
    width: 100,
    align: 'center',
    render(row: { isDownload: number }) {
      const local = row.isDownload ? '可下载' : '不可下载';
      return h('span', null, {default: () => (local)})
    }
  }, {
    title: '预览量',
    key: 'preview',
    width: 90,
    align: 'center'
  }, {
    title: '下载量',
    key: 'download',
    width: 90,
    align: 'center'
  }, {
    title: '点赞量',
    key: 'likes',
    width: 90,
    align: 'center'
  },
  {
    title: '状态',
    key: 'status',
    width: 80,
    align: 'center',
    render(row: { status: boolean | number }) {
      const enabled_color = row.status ? 'success' : 'warning';
      const enabled_text = row.status ? '正常' : '停用';
      return h(NTag,
          {
            type: enabled_color,
          },
          {
            default: () => (enabled_text),
          }
      );
    }
  }, {
    title: '排序',
    key: 'sort',
    width: 100,
    align: 'center'
  }, {
    title: '创建时间',
    key: 'createTime',
    width: 175,
  }
])
//操作列
const actionColumn = reactive({
  width: 120,
  title: "操作",
  key: "action",
  fixed: "right",
  render(record: Recordable) {
    return h(DataTableAction, {
      actions: [
        {
          label: '修改',
          onClick: handleEdit.bind(null, record),
          type: 'primary',
          permission: ['materials:edit']
        },
        {
          label: '删除',
          type: 'error',
          popConfirm: NPopconfirm,
          onPositiveClick: handleDelete.bind(null, record),
          confirm: {
            text: '确定删除当前课程资料吗？',
          },
          permission: ['materials:del']
        },
      ]
    });
  },
});
//新增、修改课程资料
const addEditModel = ref<boolean>(false);
const addEditFormRef = ref<FormInst | null>(null);
const handelSubmitLoading = ref<boolean>(false);
const chunkSize: number = 2 * 1024 * 1024; // 设置每个分片的大小  10MB
const addEditForm = ref({
  id: 0,
  title: '',
  sId:<null|number|any> null,
  isLocal: 1,
  name: '',
  img: null,
  src: <string|null|any>null,
  isDownload: 0,
  preview: 0,
  download: 0,
  likes: 0,
  status: 1,
  selected: 0,
  sort: 100,
  file_type: '',
})
const addEditFormRules = computed(() => {
  return {
    title: {
      required: true,
      trigger: ['blur', 'input'],
      message: '请填写资料标题',
    },
    sId: {
      type: 'number',
      required: true,
      trigger: ['blur', 'change'],
      message: '请选择所属课程'
    },
    isLocal: {
      type: 'number',
      required: true,
      trigger: ['blur', 'change'],
      message: '本地资料不能为空'
    },
    src: {
      required: true,
      trigger: ['blur', 'input'],
      message: addEditForm.value.isLocal == 1 ? '请上传课程资料' : '请填写远程地址',
    },
    isDownload: {
      type: 'number',
      required: true,
      trigger: ['blur', 'change'],
      message: '资料能否下载不能为空'
    },
  }
})
//查询
const handleSubmitSearch = () => {
  data_list.value.searchListData();
}
//修改
const handleEdit = (record: Recordable) => {
  addEditForm.value.id = record.id;
  addEditForm.value.title = record.title;
  addEditForm.value.sId = record.sid;
  addEditForm.value.isLocal = record.isLocal;
  addEditForm.value.src = record.src;
  addEditForm.value.img = record.img;
  addEditForm.value.name = record.name;
  addEditForm.value.isDownload = record.isDownload;
  addEditForm.value.preview = record.preview;
  addEditForm.value.download = record.download;
  addEditForm.value.selected = record.selected;
  addEditForm.value.likes = record.likes;
  addEditForm.value.status = record.status;
  addEditForm.value.sort = record.sort;
  addEditForm.value.file_type = getExtension(record.src);
  addEditModel.value = true;
}
//删除
const handleDelete = (record: Recordable) => {
  delRequest('course_m/del', record.id).then((result: ResponseResult) => {
    if (result.status === 0 && result.code === 200) {
      message.success(result.message, {
        duration: 1500,
        onLeave() {
          data_list.value.reload();
        }
      })
    } else {
      message.error(result.message);
    }
  })
}
//提交新增、修改数据
const handelSubmitData = (e: MouseEvent) => {
  e.preventDefault();
  addEditFormRef.value?.validate((errors) => {
    if (!errors) {
      handelSubmitLoading.value = true;
      const url = addEditForm.value.id ? 'course_m/edit' : 'course_m/add';
      postPutRequest(url, addEditForm.value, addEditForm.value.id ? 'PUT' : 'POST').then((result: ResponseResult) => {
        if (result.code === 200) {
          message.success(result.message, {
            duration: 1500,
            onLeave() {
              addEditModel.value = false;
              if (addEditForm.value.id) {
                data_list.value.reload();
              } else {
                data_list.value.searchListData();
              }
            }
          })
        } else {
          message.error(result.message);
          handelSubmitLoading.value = false;
        }
      })
    }
  })
}
const closeAddEditModel = () => {
  addEditForm.value.id = 0;
  addEditForm.value.title = '';
  addEditForm.value.sId = null;
  addEditForm.value.isLocal = 1;
  addEditForm.value.img = null;
  addEditForm.value.src = null;
  addEditForm.value.name = '';
  addEditForm.value.isDownload = 0;
  addEditForm.value.preview = 0;
  addEditForm.value.download = 0;
  addEditForm.value.likes = 0;
  addEditForm.value.selected = 0;
  addEditForm.value.status = 1;
  addEditForm.value.sort = 100;
  handelSubmitLoading.value = false;
}
const renderLabelSuffix = (option: SelectOption) => {
  return h('div', null, {
    default: () => [
      h('span', null, {default: () => option.name}),
      h('span', null, {default: () => '(' + option.classifyName + '/' + option.gradeName + ')'})
    ]
  })
}
//上传本地文件
let fileUploadFinish = ref<boolean>(false);
const customRequest = ({file}: UploadCustomRequestOptions) => {
  const files: any = file && file?.file;//所需上传的文件
  // 获取到文件
  let fileArr: Blob[] = sliceFile(files, chunkSize);
  // 保存文件名称
  let fileName: string = files.name;
  fileUploadFinish.value = false;
  getFileMd5(files).then(async (md5: string) => {
    for (let i = 0; i < fileArr.length; i++) {
      const data = new FormData();
      data.append("totalNumber", fileArr.length.toString());
      data.append("chunkSize", chunkSize.toString());
      data.append("chunkNumber", i.toString());
      data.append("md5", md5);
      data.append("file", new File([fileArr[i]], fileName));
      await upload(data, fileName); // 上传文件
    }
  })
}
const upload = async (data: any, name: string) => {
  try {
    postPutRequest("course_m/files", data).then((result: ResponseResult) => {
      if (result.code == 200 && result.status == 0) {
        const {data} = result;
        if (data.status == 200 && !fileUploadFinish.value) {
          fileUploadFinish.value = true;
          addEditForm.value.name = name;
          addEditForm.value.src = data.name;
          addEditForm.value.file_type = getExtension(data.name);
        }
        return; // 终止函数执行
      }
    })
  } catch (error) {
    console.error(error);
    message.error('上传失败');
  }
}
const sliceFile = (file: Blob, chunkSize: number): Blob[] => {
  const chunks: Blob[] = [];
  let start = 0;
  let end: number;
  while (start < file.size) {
    end = Math.min(start + chunkSize, file.size);
    chunks.push(file.slice(start, end));
    start = end;
  }
  return chunks;
}
const deleteFile = () => {
  addEditForm.value.name = '';
  addEditForm.value.src = null;
  addEditForm.value.file_type = '';
}
const getCourse = async () => {
  await getRequest("course/for_vip").then((result: ResponseResult) => {
    const {data} = result;
    courseOptions.value = data;
  })
}
onBeforeMount(() => {
  getCourse();
})
</script>
<style scoped lang="scss">
.upload-files {
  width: 70px;
  height: 70px;
}
</style>